/**
 * Copyright 2011 Joe Choi, All rights reserved.
 */
package tao.data.structure.tree;

import tao.data.structure.Stack;
import tao.data.structure.tree.Traversal.Event;
import static tec.data.structure.DataStructure.*;

/**
 * To build a tree by reference the structure and content of a given tree in PreOrder
 * 
 * @author Joe Choi
 */
public class PreOrderBuildHandler<S, V, T extends GrowableTree<V>> 
	extends ConcreteBuilder.AbstractHandler<S, V, T> {
	public PreOrderBuildHandler(Tree<S> source, Creation<S, V, T> creation) {
		this(null, source, creation);
	}

	public PreOrderBuildHandler(T root, Tree<S> source, Creation<S, V, T> creation) {
		setSource(source);
		treeStack = stack();
		this.creation = creation;
		this.root = root;
	}
	
	@Override
	public Traversal<S> getTraversal() {
		return(new PreOrderTraversal<S>(source));
	}

	@Override
	public void afterTraverseSubtree(Event<S> event) {
		T node = treeStack.pop();
		if(treeStack.top() != null) creation.addSubtree(treeStack.top(), node);
		/*
		System.out.println("root: " + root);
		System.out.println("parent: " + treeStack.top());
		System.out.println("node: " + node);
		*/
	}

	@Override
	public void beforeTraverseSubtree(Event<S> event) {
		// if root is specified by user, no need to build
		if(root != null && isBuildingRoot()) {
			treeStack.push(root);
		} else {
			T node = creation.create(treeStack.top(), event.getTree());
			if(isBuildingRoot()) root = node;
			treeStack.push(node);
		}		
	}
	
	private boolean isBuildingRoot() {
		return(treeStack.isEmpty());
	}
	
	private Stack<T> treeStack;
	private Creation<S, V, T> creation;
	
	/**
	 * To create a specific type of tree
	 */
	public interface Creation<S, V, T extends GrowableTree<V>> {
		public T create(T parent, Tree<S> node);
		public void addSubtree(T parent, T newTree);
	}
	
	/**
	 * The Default implementation of Creation interface
	 */
	public static abstract class AbstractCreation<S, V, T extends GrowableTree<V>> 
		implements Creation<S, V, T> {
		
		@SuppressWarnings("unchecked")
		@Override
		public void addSubtree(T parent, T newTree) {
			parent.add(newTree);			
		}
	}
}